package de.koller.aframe.util.noise;

import de.koller.aframe.util.math.FunctionPreview;
import de.koller.aframe.util.math.IFunction;
import de.koller.aframe.util.noise.n2D.Perlin2D;
import java.util.Random;

public class PerlinDistribution implements IFunction {

	public Random rnd = new Random();
	private final int startStep;
	private final int steps;
	private final float persistence;

	public PerlinDistribution( int startStep, int steps, float persistence ) {
		this.startStep = startStep;
		this.steps = steps;
		this.persistence = persistence;
	}
	
	@Override
	public float getValue( float x ) {
		return 0;
	}

	public IFunction getIterativeResult( int iterations, int ranges ) {
		return new IterativeResult( iterations, ranges );
	}
	
	private class IterativeResult implements IFunction {
		private final int iterations;
		private final int[] ranges;
		private final float heightMult;
		
		public IterativeResult( int iterations, int ranges ) {
			this.iterations = iterations;
			this.ranges = new int[ ranges ];
			
			heightMult = 1f / Perlin2D.maxHeight( startStep, steps, persistence );
			init();
		}

		private void init() {
			for( int i = 0; i < iterations; i++ ) {
				addData();
				if( i % 500_000 == 0 )
					System.out.println( i + " / " + iterations );
			}
		}
		
		private void addData() {
			float f = 0;
			for( int i = startStep; i < startStep+steps; i++ )
				f += rnd.nextFloat() * (float)Math.pow( persistence, i );
			f *= heightMult;
			
			int a = (int)(f * ranges.length);
			ranges[a]++;
		}
		
		@Override
		public float getValue( float x ) {
			if( x >= 1 || x < 0 )
				return 0;
			
			int a = (int)(x * ranges.length);
			int v = 0;
			for( int i = 0; i < a; i++ )
				v += ranges[i];
			
			return (float)(v * ( 1d / iterations ));
		}
	
	}
	
	public static void main( String[] args ) {
		PerlinDistribution p = new PerlinDistribution( 0, 5, 0.5f );
		
		FunctionPreview.dontscale( -0.05f );
		FunctionPreview.showFunction( -0.6f, 1.6f, p.getIterativeResult( 1_000_000, 1000 ) );
	}
	
}
